package fight

import (
	"net"
	"sync"
	"time"
	// "fsd/logger"
	// "go.uber.org/zap"
)

type Config struct {
	Addr                string
	SendNetChanSize     int
	RecvNetChanSize     int
	PutGameChanSize     int
	GetGameChanSize     int
	ConnReadTimeout     time.Duration // read timeout
	ConnWriteTimeout    time.Duration // write timeout
	GameTickerTime      time.Duration
	GameRoundTime       int64         // 帧回合时间
	GameSettleTime      time.Duration // 结算延时时间
	GameAllCmdsSize     int
}

type Server struct {
	*Config
	listener  net.Listener
    baseWG    sync.WaitGroup
    connWG    sync.WaitGroup
    gameWG    sync.WaitGroup
	closeOnce sync.Once
	exitChan  chan struct{}
	GameProtocoler
}

var Srv *Server = &Server{
	exitChan: make(chan struct{}),
}

func ListenAndServe() error {
	InitS2cMsg()
	l, err := Srv.Listen(Srv.Addr)
	if err != nil {
		return err
	}
	Srv.listener = l

	asyncStartChild(&Srv.baseWG, Start)
	return nil
}

func Start() {
	defer func() {
		stop()
        Srv.connWG.Wait()
        Srv.gameWG.Wait()
	}()

	for {
		select {
		case <-Srv.exitChan:
			return

		default:
		}

		conn, err := Srv.Accept(Srv.listener)
		if err != nil {
			continue
		}

		asyncStartChild(&Srv.connWG, func() {
			c := NewConn(conn)
			c.startConn()
		})
	}
}

func stop() {
	Srv.closeOnce.Do(func() {
		close(Srv.exitChan)
		Srv.listener.Close()
	})
}

func TrapDoStop() {
    stop()
    Srv.baseWG.Wait()
}

func asyncStartChild(wg *sync.WaitGroup, fn func()) {
    wg.Add(1)
	go func() {
		fn()
        wg.Done()
	}()
}

